// 版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:build（linux | openbsd）和&（mips64 | | mips64le）
// /+build linux openbsd 
// /+build mips64 mips64le 

package runtime

import (
	"runtime/internal/sys"
	"unsafe"
)

func dumpregs(c *sigctxt) {
	print("r0   ", hex(c.r0()), "\t")
	print("r1   ", hex(c.r1()), "\n")
	print("r2   ", hex(c.r2()), "\t")
	print("r3   ", hex(c.r3()), "\n")
	print("r4   ", hex(c.r4()), "\t")
	print("r5   ", hex(c.r5()), "\n")
	print("r6   ", hex(c.r6()), "\t")
	print("r7   ", hex(c.r7()), "\n")
	print("r8   ", hex(c.r8()), "\t")
	print("r9   ", hex(c.r9()), "\n")
	print("r10  ", hex(c.r10()), "\t")
	print("r11  ", hex(c.r11()), "\n")
	print("r12  ", hex(c.r12()), "\t")
	print("r13  ", hex(c.r13()), "\n")
	print("r14  ", hex(c.r14()), "\t")
	print("r15  ", hex(c.r15()), "\n")
	print("r16  ", hex(c.r16()), "\t")
	print("r17  ", hex(c.r17()), "\n")
	print("r18  ", hex(c.r18()), "\t")
	print("r19  ", hex(c.r19()), "\n")
	print("r20  ", hex(c.r20()), "\t")
	print("r21  ", hex(c.r21()), "\n")
	print("r22  ", hex(c.r22()), "\t")
	print("r23  ", hex(c.r23()), "\n")
	print("r24  ", hex(c.r24()), "\t")
	print("r25  ", hex(c.r25()), "\n")
	print("r26  ", hex(c.r26()), "\t")
	print("r27  ", hex(c.r27()), "\n")
	print("r28  ", hex(c.r28()), "\t")
	print("r29  ", hex(c.r29()), "\n")
	print("r30  ", hex(c.r30()), "\t")
	print("r31  ", hex(c.r31()), "\n")
	print("pc   ", hex(c.pc()), "\t")
	print("link ", hex(c.link()), "\n")
	print("lo   ", hex(c.lo()), "\t")
	print("hi   ", hex(c.hi()), "\n")
}

// go:nosplit 
// go:nowritebarrierc 
func (c *sigctxt) sigpc() uintptr { return uintptr(c.pc()) }

func (c *sigctxt) sigsp() uintptr { return uintptr(c.sp()) }
func (c *sigctxt) siglr() uintptr { return uintptr(c.link()) }
func (c *sigctxt) fault() uintptr { return uintptr(c.sigaddr()) }

// preparePanic将堆栈设置为类似于对signamic的调用。
func (c *sigctxt) preparePanic(sig uint32, gp *g) {
	// 我们安排链接，pc假装惊慌失措
	// 函数直接调用SIGMANIC。
	// 始终将链接保存到堆栈，以便正确处理叶
	// 函数中的错误。这粉碎了堆栈帧，但无论如何，我们不会回到那里。
	sp := c.sp() - sys.PtrSize
	c.set_sp(sp)
	*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()

	pc := gp.sigpc

	if shouldPushSigpanic(gp, pc, uintptr(c.link())) {
		// 让它看起来像一台叫做SIGMANIC的故障PC。
		c.set_link(uint64(pc))
	}

	// 如果我们因外部C代码
	sigpanicPC := uint64(funcPC(sigpanic))
	c.set_r28(sigpanicPC >> 32 << 32) // RSB寄存器
	c.set_r30(uint64(uintptr(unsafe.Pointer(gp))))
	c.set_pc(sigpanicPC)
}

func (c *sigctxt) pushCall(targetPC, resumePC uintptr) {
	// 而惊慌失措，请将LR推到堆栈中，因为我们将对其进行重击，以便
	// 推送调用。正在推送的函数负责
	// 恢复LR并设置SP。
	// gentraceback知道这个额外的插槽。
	sp := c.sp() - 8
	c.set_sp(sp)
	*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
	// 设置PC和LR，使其假装发送信号的函数
	// 在resumePC调用targetPC。
	c.set_link(uint64(resumePC))
	c.set_pc(uint64(targetPC))
}
